#include "AirQuality.h"

AirQuality::AirQuality(HardwareSerial& serial) : _serial(serial) {
  _co2Value = 0;
  _ch2oValue = 0;
  _tvocValue = 0;
  _pm25Value = 0;
  _pm10Value = 0;
  _temperature = 0;
  _humidity = 0;
}

void AirQuality::begin(unsigned long baud, uint8_t config, int8_t rxPin, int8_t txPin) {
  _serial.begin(baud, config, rxPin, txPin);
}

bool AirQuality::readAllData() {
  if (_serial.available() >= 17) {
    uint8_t buffer[17];
    for (int i = 0; i < 17; i++) {
      buffer[i] = _serial.read();
    }

    if (buffer[0] == 0x3C && buffer[1] == 0x02) {
      uint8_t calculatedChecksum = 0;
      for (int i = 0; i < 16; i++) {
        calculatedChecksum += buffer[i];
      }
      calculatedChecksum &= 0xFF;

      if (calculatedChecksum == buffer[16]) {
        _co2Value = (buffer[2] << 8) | buffer[3];
        _ch2oValue = (buffer[4] << 8) | buffer[5];
        _tvocValue = (buffer[6] << 8) | buffer[7];
        _pm25Value = (buffer[8] << 8) | buffer[9];
        _pm10Value = (buffer[10] << 8) | buffer[11];

        int tempInt = buffer[12];
        int tempDec = buffer[13];
        if (tempInt & 0x80) {
          tempInt &= 0x7F;
          _temperature = -((float)tempInt + (float)tempDec / 100);
        } else {
          _temperature = (float)tempInt + (float)tempDec / 100;
        }

        _humidity = (float)buffer[14] + (float)buffer[15] / 100;

        return true;
      }
    }
  }
  return false;
}

unsigned int AirQuality::getCO2() {
  return _co2Value;
}

unsigned int AirQuality::getCH2O() {
  return _ch2oValue;
}

unsigned int AirQuality::getTVOC() {
  return _tvocValue;
}

unsigned int AirQuality::getPM25() {
  return _pm25Value;
}

unsigned int AirQuality::getPM10() {
  return _pm10Value;
}

float AirQuality::getTemperature() {
  return _temperature;
}

float AirQuality::getHumidity() {
  return _humidity;
}

const char* AirQuality::getCO2Unit() {
  return "ppm";
}

const char* AirQuality::getCH2OUnit() {
  return "ug/m3";
}

const char* AirQuality::getTVOCUnit() {
  return "ug/m3";
}

const char* AirQuality::getPM25Unit() {
  return "ug/m3";
}

const char* AirQuality::getPM10Unit() {
  return "ug/m3";
}

const char* AirQuality::getTemperatureUnit() {
  return "℃";
}

const char* AirQuality::getHumidityUnit() {
  return "%RH";
}